package com.pig4cloud.pigx.contract.executer.trade.handler.impl;

import com.pig4cloud.pigx.common.customize.enums.CommonDictEnum;
import com.pig4cloud.pigx.common.customize.mysql.utils.MysqlUtil;
import com.pig4cloud.pigx.common.customize.security.utils.SecurityUtil;
import com.pig4cloud.pigx.common.customize.utils.CommonUtil;
import com.pig4cloud.pigx.contract.bo.ContractTradeHandleBO;
import com.pig4cloud.pigx.contract.bo.ContractTradeNewBO;
import com.pig4cloud.pigx.contract.entity.ContractOrder;
import com.pig4cloud.pigx.contract.enums.ContractOrderEnum;
import com.pig4cloud.pigx.contract.executer.position.supporter.PositionCalculator;
import com.pig4cloud.pigx.contract.executer.trade.handler.TradeHandlerManager;
import com.pig4cloud.pigx.contract.mapper.ContractOrderMapper;
import com.pig4cloud.pigx.contract.mapper.ContractPositionMapper;
import com.pig4cloud.pigx.contract.mapper.ContractTradeMapper;
import com.pig4cloud.pigx.contract.mapstruct.ContractTradeStruct;
import com.pig4cloud.pigx.contract.mongo.entity.ContractOrderMongo;
import com.pig4cloud.pigx.contract.mongo.entity.ContractTradeMongo;
import com.pig4cloud.pigx.contract.utils.ContractUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * 默认订单撮合处理器
 *
 * @since 2022/8/17 21:26
 */
@Component
public class RobotTradeHandler extends AbstractTradeHandler
        implements InitializingBean {

    protected final TradeHandlerManager tradeHandlerManager;

    /**
     * 有参构造函数
     * <p>同时给父级对象赋值
     *
     * @since 2022/8/19 14:47
     */
    public RobotTradeHandler(ContractOrderMapper contractOrderMapper,
                             ContractTradeMapper contractTradeMapper,
                             ContractPositionMapper contractPositionMapper,
                             RedisTemplate redis,
                             MongoTemplate mongo,
                             CommonUtil commonUtil,
                             MysqlUtil mysqlUtil,
                             SecurityUtil securityUtil,
                             ContractUtils contractUtils,
                             PositionCalculator positionCalculator,
                             TradeHandlerManager tradeHandlerManager) {
        super(contractOrderMapper, contractTradeMapper, contractPositionMapper, redis, mongo, commonUtil, mysqlUtil, securityUtil, contractUtils, positionCalculator);
        this.tradeHandlerManager = tradeHandlerManager;
    }

    /**
     * 当前对象创建后
     *
     * @since 2022/8/17 14:36
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        // 注册到manager
        tradeHandlerManager.getHandlerList().add(this);
    }

    /**
     * 判断是否支持
     *
     * @param trade 成交记录
     * @return {@link boolean}
     * @since 2022/8/17 11:20
     */
    @Override
    public boolean support(ContractTradeMongo trade) {
        // 是机器人，开仓
        return Objects.equals(CommonDictEnum.YesOrNo.YES.getValue(), trade.getIsRobot())
                && Objects.equals(ContractOrderEnum.OperationType.OPEN.getValue(), trade.getOperationType());
    }

    /**
     * 成交记录处理
     *
     * @param bo bo
     * @since 2022/8/17 11:15
     */
    @Override
    public void handle(ContractTradeHandleBO bo) {
        ContractTradeMongo trade = bo.getMongo();
        List<ContractTradeNewBO> list = bo.getNewBoList();

        // 转换为BO
        ContractTradeNewBO taker = ContractTradeStruct.INSTANCE.mongo2TradeNewBO(trade);
        list.add(taker);

        // 查询对手成交记录，转换为BO
        ContractTradeMongo makerTrade = getTrade(trade.getMakerTradeId());
        ContractTradeNewBO maker = ContractTradeStruct.INSTANCE.mongo2TradeNewBO(makerTrade);
        taker.setMakerBo(maker);
        list.add(maker);

        // 遍历，分别处理
        list.forEach(i -> {
            // 初始化信息
            initParam(i);
            // 持久化成交记录
            saveToMysql(i);
        });

        // 同时处理订单，防止死锁
        handleOrder(list);
    }

    /**
     * 持久化到mysql
     *
     * @param bo bo
     * @since 2022/8/20 16:06
     */
    @Override
    protected void saveToMysql(ContractTradeNewBO bo) {
        super.saveToMysql(bo);
    }

    /**
     * 初始化参数
     *
     * @param trade 成交记录
     * @since 2022/8/19 16:45
     */
    @Override
    protected void initParam(ContractTradeNewBO trade) {
        // positionId赋值0
        trade.setPositionId(0L);
    }

    /**
     * 处理成功
     *
     * @param bo bo
     * @since 2022/8/17 11:31
     */
    @Override
    public void success(ContractTradeHandleBO bo) {
        List<ContractTradeNewBO> list = bo.getNewBoList();

        // 提交本地事务
        mysqlUtil.commitLocalTx();

        // 删除缓存
        list.forEach(i -> {
            // 发送k线临时成交记录&币对最新成交记录消息
//			contractUtils.sendContractInitTradeMq(i);
            // 处理订单
            ContractOrder order = i.getOrder();
            // 完全成交
            i.setIsAllDeal(order.getNoDealNum().compareTo(BigDecimal.ZERO) == 0);
            removeMongo(i);

            // 如果完全成交，发送迁移历史订单消息
            if (i.getIsAllDeal()) {
                contractUtils.sendOrderMigrate(Collections.singletonList(i.getOrderId()));
            }
        });
    }

    /**
     * 删除mongo中的order
     *
     * @param bo bo
     * @since 2022/8/20 18:42
     */
    @Override
    protected void removeOrder(ContractTradeNewBO bo) {
        // 删除order缓存
        Criteria removeTaker = Criteria.where("id").is(bo.getOrderId());
        mongo.remove(Query.query(removeTaker),
                ContractOrderMongo.class,
                ContractUtils.getOrderBookName(bo.getIsBuy()));
    }
}
